package at.ac.tuwien.swa

import java.io.File
import scala.annotation.tailrec
import scala.collection.mutable
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.concurrent.duration._
import scala.util.{Properties, Random}

package object sparrow {

	lazy val CONFIG_DIR = new File(Properties.propOrElse("swazam.home", Properties.userHome + File.separator + ".swazam"))
	lazy val CONFIG_FILE_PEER = new File(CONFIG_DIR, "peer.conf")

	val DEFAULT_PEER_PORT = 32768
	val HOP_COUNT = 10
	val PEER_TIMEOUT = 1.minute
	val SESSION_DURATION = 10.minutes
	val SERVICE_URL = "http://localhost:8080/remoting/peer"
	val SEARCH_COSTS = 1
	val SEARCH_REWARD = 2
	val WELCOME_CREDITS = 10

	CONFIG_DIR.mkdirs()

	@tailrec
	@inline
	private def randomSubset[A](count: Int = 1, src: IndexedSeq[A], target: Set[A] = Set.empty[A]): Set[A] = target match {
		case _ if count <= 0 => target
		case _ if count > src.size => target ++: src.toSet
		case _ if count <= target.size => target
		case _ => randomSubset(count, src, target + src(Random nextInt src.size))
	}

	implicit class SetOps[T](val s: Set[T]) extends AnyVal {
		def subset(n: Int): Set[T] = randomSubset(n, s.toIndexedSeq)
	}

	implicit class MutableSetOps[T](val s: mutable.Set[T]) extends AnyVal {
		def subset(n: Int): Set[T] = randomSubset(n, s.toIndexedSeq)
	}

	def scheduleAt(t: Long)(func: => Unit): Future[Unit] = schedule((t - System.currentTimeMillis).millis)(func)

	def schedule(t: FiniteDuration)(func: => Unit): Future[Unit] = {
		val future = Future(blocking(Thread sleep (0L max t.toMillis)))
		future.onComplete(f => func)
		future
	}

	implicit class AnyRefOps[T <: AnyRef](val obj: T) extends AnyVal {
		def ==?(other: Any) = if (other == null) true else obj == other

		def ?==(other: Any) = if (obj == null) true else obj == other

		def ?==?(other: Any) = if (obj == null || other == null) true else obj == other
	}

}
